package life.ks98.community.service;

import life.ks98.community.dto.PaginationDTO;
import life.ks98.community.dto.QuestionDTO;
import life.ks98.community.dto.QuestionQueryDTO;
import life.ks98.community.exception.CustomizeErrorCode;
import life.ks98.community.exception.CustomizeException;
import life.ks98.community.mapper.QuestionExtMapper;
import life.ks98.community.mapper.QuestionMapper;
import life.ks98.community.mapper.UserMapper;
import life.ks98.community.model.Question;
import life.ks98.community.model.QuestionExample;
import life.ks98.community.model.User;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;


/**
 * @author Kyrie
 * @date 2021/2/11 - 14:11
 */
@Service
public class QuestionService {
    @Autowired
    private QuestionMapper questionMapper;

    @Autowired
    private QuestionExtMapper questionExtMapper;

    @Autowired
    private UserMapper userMapper;

    public PaginationDTO<QuestionDTO> list(String search, Integer page, Integer size) {
        if (org.apache.commons.lang3.StringUtils.isNotBlank(search)) {
            String[] tags = org.apache.commons.lang3.StringUtils.split(search, " ");
            search = Arrays
                    .stream(tags)
                    .filter(org.apache.commons.lang3.StringUtils::isNotBlank)
                    .map(t -> t.replace("+", "").replace("*", "").replace("?", ""))
                    .filter(org.apache.commons.lang3.StringUtils::isNotBlank)
                    .collect(Collectors.joining("|"));
        }
        // 分页聚合dto
        PaginationDTO<QuestionDTO> paginationDTO = new PaginationDTO<>();
        // 总页码
        Integer totalPage;
        // 总条数
        QuestionQueryDTO questionQueryDTO = new QuestionQueryDTO();
        questionQueryDTO.setSearch(search);
        Integer totalCount = questionExtMapper.countBySearch(questionQueryDTO);
        if (totalCount % size == 0) {
            totalPage = totalCount / size;
        } else {
            totalPage = totalCount / size + 1;
        }
        // 合理化页码参数
        if (page < 1) {
            page = 1;
        }
        if (page > totalPage) {
            page = totalPage;
        }
        // 处理分页聚合dto的展示数据
        paginationDTO.setPagination(totalPage, page);

        Integer offset = size * (page-1);
        questionQueryDTO.setSize(size);
        questionQueryDTO.setPage(offset);
        List<Question> questions = questionExtMapper.selectBySearch(questionQueryDTO);
        List<QuestionDTO> questionDTOLists = new ArrayList<>();
        questions.forEach((q) -> {
            User user = userMapper.selectByPrimaryKey(q.getCreator());
            QuestionDTO questionDTO = new QuestionDTO();
            BeanUtils.copyProperties(q, questionDTO);
            questionDTO.setUser(user);
            questionDTOLists.add(questionDTO);
        });
        paginationDTO.setData(questionDTOLists);
        return paginationDTO;
    }

    public PaginationDTO list(Long userId, Integer page, Integer size) {
        // 分页聚合dto
        PaginationDTO<QuestionDTO> paginationDTO = new PaginationDTO<>();
        // 总页码
        Integer totalPage;
        // 总条数
        QuestionExample questionExample = new QuestionExample();
        questionExample.createCriteria()
                .andCreatorEqualTo(userId);
        Integer totalCount = (int) questionMapper.countByExample(questionExample);
        if (totalCount % size == 0) {
            totalPage = totalCount / size;
        } else {
            totalPage = totalCount / size + 1;
        }
        // 合理化页码参数
        if (page < 1) {
            page = 1;
        }
        if (page > totalPage) {
            page = totalPage;
        }
        // 处理分页聚合dto的展示数据
        paginationDTO.setPagination(totalPage, page);

        Integer offset = size * (page-1);
        questionExample = new QuestionExample();
        questionExample.createCriteria()
                .andCreatorEqualTo(userId);
        questionExample.setOrderByClause("gmt_create desc");
        List<Question> questions = questionMapper.selectByExampleWithRowbounds(questionExample, new RowBounds(offset, size));
        List<QuestionDTO> questionDTOLists = new ArrayList<>();
        questions.forEach((q) -> {
            User user = userMapper.selectByPrimaryKey(q.getCreator());
            QuestionDTO questionDTO = new QuestionDTO();
            BeanUtils.copyProperties(q, questionDTO);
            questionDTO.setUser(user);
            questionDTOLists.add(questionDTO);
        });
        paginationDTO.setData(questionDTOLists);
        return paginationDTO;
    }

    public void create(Question question) {
        if (ObjectUtils.isEmpty(question.getCommentCount())) {
            question.setCommentCount(0);
        }
        if (ObjectUtils.isEmpty(question.getLikeCount())) {
            question.setLikeCount(0);
        }
        if (ObjectUtils.isEmpty(question.getViewCount())) {
            question.setViewCount(0);
        }
        question.setGmtCreate(System.currentTimeMillis());
        question.setGmtModified(question.getGmtCreate());
        questionMapper.insert(question);
    }

    public QuestionDTO getById(Long id) {
        Question question = questionMapper.selectByPrimaryKey(id);
        if (ObjectUtils.isEmpty(question)) {
            throw new CustomizeException(CustomizeErrorCode.QUESTION_NOT_FOUND);
        }
        QuestionDTO questionDTO = new QuestionDTO();
        BeanUtils.copyProperties(question, questionDTO);
        User user = userMapper.selectByPrimaryKey(question.getCreator());
        questionDTO.setUser(user);
        return questionDTO;
    }

    public void createOrUpdate(Question question) {
        Question dbQuestion = questionMapper.selectByPrimaryKey(question.getId());
        if (dbQuestion == null) {
            // 插入
            create(question);
        } else {
            // 更新
            Question updateQuestion = new Question();
            updateQuestion.setTag(question.getTag());
            updateQuestion.setGmtModified(System.currentTimeMillis());
            updateQuestion.setDescription(question.getDescription());
            updateQuestion.setTitle(question.getTitle());
            QuestionExample questionExample = new QuestionExample();
            questionExample.createCriteria()
                    .andIdEqualTo(question.getId());
            int update = questionMapper.updateByExampleSelective(updateQuestion, questionExample);
            if (update != 1) {
                throw new CustomizeException(CustomizeErrorCode.QUESTION_NOT_FOUND);
            }
        }
    }

    public void incView(Long id) {
        Question question = new Question();
        question.setId(id);
        question.setViewCount(1);
        questionExtMapper.incView(question);
    }

    public List<QuestionDTO> selectRelated(QuestionDTO queryDTO) {
        if (StringUtils.isEmpty(queryDTO.getTag())) {
            return new ArrayList<>();
        }
        String[] tags = org.apache.commons.lang3.StringUtils.split(queryDTO.getTag(), ",");
        String regexpTag = Arrays.stream(tags)
                .filter(org.apache.commons.lang3.StringUtils::isNoneBlank)
                .map(t -> t.replace("+", "").replace("*", "").replace("?", ""))
                .filter(org.apache.commons.lang3.StringUtils::isNotBlank)
                .collect(Collectors.joining("|"));
        Question question = new Question();
        question.setId(queryDTO.getId());
        question.setTag(regexpTag);

        List<Question> questions = questionExtMapper.selectRelated(question);
        List<QuestionDTO> questionDTOS = questions.stream().map(question1 -> {
            QuestionDTO questionDTO = new QuestionDTO();
            BeanUtils.copyProperties(question1, questionDTO);
            return questionDTO;
        }).collect(Collectors.toList());
        return questionDTOS;
    }
}
